package com.jy.modules.cims.buyback.service;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jodd.util.StringUtil;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.jy.modules.cims.common.CimsConstant;
import com.jy.modules.cims.common.exception.CimsExceptionConstant;
import com.jy.modules.cims.common.sysUtils.CollectionsUtils;
import com.jy.modules.cims.component.common.service.TCMmTransConfigService;
import com.jy.modules.cims.component.common.service.TCMmTransExceptionService;
import com.jy.modules.cims.data.common.dao.TCMmDealMatchDao;
import com.jy.modules.cims.data.common.dto.TCMmCooperorgDealDTO;
import com.jy.modules.cims.data.common.dto.TCMmCreditDealDetailDTO;
import com.jy.modules.cims.data.common.dto.TCMmCreditDetailDTO;
import com.jy.modules.cims.data.common.dto.TCMmDealMatchDTO;
import com.jy.modules.cims.data.common.dto.TCMmTransConfigDTO;
import com.jy.modules.cims.data.common.dto.TCMmTransExceptionDTO;
import com.jy.modules.cims.data.dto.CreditDetailDto;
import com.jy.modules.cims.data.dto.credit.RedeemParamDto;
import com.jy.modules.cims.data.dto.credit.RedeemResultDto;
import com.jy.modules.cims.data.interact.core.credit.response.ResponseBackCreditValueDTO;
import com.jy.modules.cims.deal.service.DealService;
import com.jy.modules.cims.transexception.service.TransExceptionService;

/**
 * 贷款回购确认操作
 */
@Service("com.jy.modules.cims.buyback.service.BuyBackConfirmService")
public class BuyBackConfirmService extends BuyBackCommonService {

	private static final Logger logger = LoggerFactory.getLogger(BuyBackConfirmService.class);
	
    @Autowired
   	@Qualifier("com.jy.modules.cims.component.common.service.TCMmTransExceptionService")
   	private TCMmTransExceptionService tCMmTransExceptionService;
    
    @Autowired
	@Qualifier("com.jy.modules.cims.component.common.service.TCMmTransConfigService")
    private TCMmTransConfigService transConfigService;
    
    @Autowired
	@Qualifier("com.jy.modules.cims.transexception.service.TransExceptionService")
    private TransExceptionService transExceptionService;
    
	@Autowired
	@Qualifier("com.jy.modules.cims.deal.service.DealService")
	public DealService dealService;
	
    @Autowired
   	private TCMmDealMatchDao dealMatchDao;
    
	
	/**
	 * 贷款回购交易两个事务同时处理(处理贷款转出批量回购及贷款转出月还)
	 * 读取事务控制表数据,若当前交易流水的整个事务未执行，则执行整个事务，若执行过事务，并且其中单个事务失败，则重新执行单个事务，保证失败事务在界面点击时可重复执行
     * @throws Exception 
     * @Title doLoanTransferRedeem
     * @return 
     * @author yanjingying
     * @date 2015-12-17-下午11:47:00
     * @update
     * @throws
	 * */
	public Map<String, String> doBuyBackConfirm(TCMmCooperorgDealDTO cooperorgDealDTO, String dealCode) throws Exception{
		String returnMsg = "";   //返回信息
		Map<String, String> resultMapA = new HashMap<String, String>();
		Map<String, String> resultMapB = new HashMap<String, String>();
		
		//读取事务控制表数据,若当前交易流水的整个事务未执行，则执行整个事务，若执行过事务，并且其中单个事务失败，则重新执行单个事务，保证失败事务可重复执行
     	Map<String, Object> hashMap = new HashMap<String, Object>();
     	TCMmTransExceptionDTO transExceptionDTO = new TCMmTransExceptionDTO();
		transExceptionDTO.setTransEnName(CimsConstant.COOPERORG_TRANS_EN_NAME_T001);    //事务名称：贷款回购交易发送核心整体事务
		transExceptionDTO.setDealCode(dealCode);   //交易流水号
		hashMap.put("dto", transExceptionDTO);
     	List<TCMmTransExceptionDTO> transExceptionDTOList = tCMmTransExceptionService.searchTCMmTransException(hashMap);
     	
     	/**第一次调用
     	 * 若A成功，则调用B，此时异常表中有A-0000, B-0000或0001或9998;
     	 * 若A失败，不调用B，此时异常表中有A-0001*/
     	
     	if(CollectionsUtils.isEmpty(transExceptionDTOList)) {
     		//调用事务A,事务A成功调用事务B
    		resultMapA = doLoanTransferRedeemA(cooperorgDealDTO, null);
    		if(CimsConstant.RET_CODE_SUC.equals(resultMapA.get("resultCode"))){
        		resultMapB = doLoanTransferRedeemB(cooperorgDealDTO, null);
    		}
     	}
     	
     	 /**第二次调用，A失败的情况下继续调用A，直至A成功，方可调B*/
     	else if(transExceptionDTOList.size() == 1){
     		String frontNo = null;
     		if(transExceptionDTOList.get(0).getRetCode().equals(CimsConstant.RET_CODE_TIMEOUT)){
     			frontNo = transExceptionDTOList.get(0).getFrontTransNo();
     		} 
    		//调用事务A,事务A成功调用事务B
    		resultMapA = doLoanTransferRedeemA(cooperorgDealDTO, frontNo);
    		if(CimsConstant.RET_CODE_SUC.equals(resultMapA.get("resultCode"))){
        		resultMapB = doLoanTransferRedeemB(cooperorgDealDTO, null);
    		}
     		
     	}
     	
     	/**第N次调用，但有两条记录后，说明此时A-0000,B-0000或0001或9998*/
     	else if(transExceptionDTOList.size() == 2){
     		for(TCMmTransExceptionDTO dto : transExceptionDTOList){
     			if(CimsConstant.COOPERORG_TRANS_T001_A.equals(dto.getTransNo())){
 					if(CimsConstant.RET_CODE_FAIL.equals(dto.getRetCode())){
     					//失败则重新调用
 						resultMapA = doLoanTransferRedeemA(cooperorgDealDTO, null);
     				} else if (CimsConstant.RET_CODE_TIMEOUT.equals(dto.getRetCode())) {
     					//超时
     					resultMapA = doLoanTransferRedeemA(cooperorgDealDTO, dto.getFrontTransNo());
     				} else {
     					//成功则直接返回结果
     					resultMapA = new HashMap<String, String>();
     					resultMapA.put("resultCode", dto.getRetCode());
     					resultMapA.put("resultMsg", dto.getRetMsg());
     				}
     			}
     			//事务B失败，直接调用事务B
     			else if(CimsConstant.COOPERORG_TRANS_T001_B.equals(dto.getTransNo())){
     				if(CimsConstant.RET_CODE_FAIL.equals(dto.getRetCode())){
     					//失败则重新调用
     					resultMapB = doLoanTransferRedeemB(cooperorgDealDTO, null);
     				} else if (CimsConstant.RET_CODE_TIMEOUT.equals(dto.getRetCode())) {
     					//超时
     					resultMapB = doLoanTransferRedeemB(cooperorgDealDTO, dto.getFrontTransNo());
     				} else {
     					//成功\无需调用、则直接返回结果
     					resultMapB = new HashMap<String, String>();
     					resultMapB.put("resultCode", dto.getRetCode());
     					resultMapB.put("resultMsg", dto.getRetMsg());
     				}
     			}
     			//如果A事务未成功的情况，跳出循环不调用B
     			if (!CimsConstant.RET_CODE_SUC.equals(resultMapA.get("resultCode"))) {
     				break;
     			}
     		}
     	}
     	
     	//两个事务必须同时成功，才可更新交易状态
     	String totalRes = "false";
     	//A成功、B成功|无需调用
		if(CimsConstant.RET_CODE_SUC.equals(resultMapA.get("resultCode")) 
				&& (CimsConstant.RET_CODE_SUC.equals(resultMapB.get("resultCode")) 
						|| CimsConstant.RET_CODE_NO_INVOKE.equals(resultMapB.get("resultCode")) )){
			//A成功、B成功/无需调用：更新【合作机构交易流水表】交易状态为03-回购完成
			cooperorgDealDTO.setCooperativeAgencyDealStatus(CimsConstant.DEAL_STATUS_FINISH); //交易状态为03-回购完成
			cooperorgDealDTO.setDealDate(new java.util.Date());  //交易日期
			cooperorgDealDTO.setModifyTime(new Timestamp(System.currentTimeMillis()));        //更新时间
			cooperorgDealService.updateTCMmCooperorgDeal(cooperorgDealDTO);
			totalRes = "true";
		}else if(  
			//A失败 B空
			//A失败 B失败
			//A失败 B无需调用
			//以上情况除外，需改为回购中
			!(CimsConstant.RET_CODE_FAIL.equals(resultMapA.get("resultCode")) && StringUtil.isEmpty(resultMapB.get("resultCode")))
			&& !(CimsConstant.RET_CODE_FAIL.equals(resultMapA.get("resultCode")) && CimsConstant.RET_CODE_FAIL.equals(resultMapB.get("resultCode")))
			&& !(CimsConstant.RET_CODE_FAIL.equals(resultMapA.get("resultCode")) && CimsConstant.RET_CODE_NO_INVOKE.equals(resultMapB.get("resultCode")))
		){
			//A成功、B失败：更新【合作机构交易流水表】交易状态为02-回购中
			cooperorgDealDTO.setCooperativeAgencyDealStatus(CimsConstant.DEAL_STATUS_WAY); //交易状态为02-回购中
			cooperorgDealDTO.setDealDate(new java.util.Date());  //交易日期
			cooperorgDealDTO.setModifyTime(new Timestamp(System.currentTimeMillis()));        //更新时间
			cooperorgDealService.updateTCMmCooperorgDeal(cooperorgDealDTO);
		}
		//返回前台信息
		returnMsg =  (resultMapA.get("resultMsg") == null ? "" : resultMapA.get("resultMsg")) + "@@"
					+ (resultMapB.get("resultMsg") == null ? "" : resultMapB.get("resultMsg"));
		
		Map<String, String> retMap = new HashMap<String, String>();
		retMap.put("totalRes", totalRes);
		retMap.put("totalMsg", returnMsg);
     	return retMap;
	}
	
	
	/**
	 * 贷款回购
     * @throws Exception 
     * @Title doLoanTransferRedeemA
     * @return 
     * @author yanjingying
     * @date 2015-12-23-下午11:47:00
     * @update
     * @throws
	 * */
	private Map<String, String> doLoanTransferRedeemA(TCMmCooperorgDealDTO cooperorgDealDTO, String frontTransNo) throws Exception{
		
		if(frontTransNo == null || "".equals(frontTransNo)){
    		frontTransNo = iInteractAssist.getInteractNo();   //获取前置接口交易流水号
    	}
		
		RedeemResultDto redeemResultDto = new RedeemResultDto();
		String retCode = ""; //返回码
		String retMsg = "";//返回message
//		Long exceptionPrimaryKeyId; //事务异常表主键
		Map<String, String> resultMap = new HashMap<String, String>();
		TCMmTransConfigDTO transConfigDTO = new TCMmTransConfigDTO();
		Map<String, Object> searchParams = new HashMap<String, Object>();
		transConfigDTO.setTransEnName(CimsConstant.COOPERORG_TRANS_EN_NAME_T001);  //贷款回购交易发送核心整体事务
		transConfigDTO.setTransNo(CimsConstant.COOPERORG_TRANS_T001_A);
		searchParams.put("dto", transConfigDTO);
		List<TCMmTransConfigDTO>  tCMmTransConfigDTOList = transConfigService.searchTCMmTransConfig(searchParams);
		if(tCMmTransConfigDTOList != null && tCMmTransConfigDTOList.size() > 0){
			//得到事务配置信息
			TCMmTransConfigDTO dto = tCMmTransConfigDTOList.get(0);
			//前端处理1：贷款转出批量回购
			try {
				Map<String, Object> rsMap = this.doBuyBackContract(cooperorgDealDTO, frontTransNo);
				redeemResultDto = (RedeemResultDto)rsMap.get("dto");
				retCode = redeemResultDto.getRetCode();
				if (CimsConstant.RET_CODE_SUC.equals(redeemResultDto.getRetCode())) {
					retMsg = "贷款回购接口调用成功!";
					redeemResultDto.setRetMsg(retMsg);
				}
				redeemResultDto.setFrontTransNo(frontTransNo);
				transExceptionService.saveTransException(dto, redeemResultDto, retCode, cooperorgDealDTO.getDealCode());
			} catch (Exception e) {
				logger.error("贷款回购接口异常，异常信息如下："+e.getMessage());
				if (e.getMessage().indexOf(CimsExceptionConstant.INTERACT_NETWORK_ERROR) > -1) {
					retCode = CimsConstant.RET_CODE_TIMEOUT;  //超时
				} else {
					retCode = CimsConstant.RET_CODE_FAIL;
				}
				retMsg = "贷款回购接口调用失败："+ e.getMessage()+"!";
				retMsg = retMsg.length() > 100 ? retMsg.substring(0, 100) : retMsg;
				redeemResultDto.setRetCode(retCode);
				redeemResultDto.setRetMsg(retMsg);
				redeemResultDto.setFrontTransNo(frontTransNo);
				transExceptionService.saveTransException(dto, redeemResultDto, retCode, cooperorgDealDTO.getDealCode());
				/*result = this.doLoanTransferRedeemInterfaceTransException(cooperorgDealDTO, dto, retCode, exceptionPrimaryKeyId, i);*/
			}
		}else{
			retMsg = "贷款回购事务配置缺失!";
			retCode = CimsConstant.RET_CODE_FAIL;
		}
		
		resultMap.put("resultCode", retCode);
		resultMap.put("resultMsg", retMsg);
		return resultMap;
	}
	
	
	/**
	 *  月还匹配债权赎回 
     * @throws Exception 
     * @Title doLoanTransferRedeemA
     * @return 
     * @author yanjingying
     * @date 2015-12-23-下午11:47:00
     * @update
     * @throws
	 * */
	private Map<String, String> doLoanTransferRedeemB(TCMmCooperorgDealDTO cooperorgDealDTO, String frontTransNo) throws Exception{
		if(frontTransNo == null || "".equals(frontTransNo)){
    		frontTransNo = iInteractAssist.getInteractNo();   //获取前置接口交易流水号
    	}
		RedeemResultDto redeemResultDto = new RedeemResultDto();
		String retCode = ""; //返回码
		String retMsg = "";//返回message
		Map<String, String> resultMap = new HashMap<String, String>();
		TCMmTransConfigDTO transConfigDTO = new TCMmTransConfigDTO();
		Map<String, Object> searchParams = new HashMap<String, Object>();
		transConfigDTO.setTransEnName(CimsConstant.COOPERORG_TRANS_EN_NAME_T001);  //贷款回购交易发送核心整体事务
		transConfigDTO.setTransNo(CimsConstant.COOPERORG_TRANS_T001_B);
		searchParams.put("dto", transConfigDTO);
		List<TCMmTransConfigDTO>  tCMmTransConfigDTOList = transConfigService.searchTCMmTransConfig(searchParams);
		if(tCMmTransConfigDTOList != null && tCMmTransConfigDTOList.size() > 0){
			//得到事务配置信息
			TCMmTransConfigDTO dto = tCMmTransConfigDTOList.get(0);
			//前端处理1：贷款转出批量回购
			try {
				Map<String, Object> rsMap = this.doBuyBackCredit(cooperorgDealDTO, frontTransNo);
				String isInvoke = (String)rsMap.get("isInvoke");
				if ("true".equals(isInvoke)) {
					redeemResultDto = (RedeemResultDto)rsMap.get("dto");
					retCode = redeemResultDto.getRetCode();
					if (CimsConstant.RET_CODE_SUC.equals(redeemResultDto.getRetCode())) {
						retMsg = "月还匹配债权赎回接口调用成功!";
						redeemResultDto.setRetMsg(retMsg);
					}
					redeemResultDto.setFrontTransNo(frontTransNo);
				} else {
					retCode = CimsConstant.RET_CODE_NO_INVOKE;
//					retMsg = "月还匹配债权赎回接口无需调用!";
				}
				transExceptionService.saveTransException(dto, redeemResultDto, retCode, cooperorgDealDTO.getDealCode());
			} catch (Exception e) {
				logger.error("月还匹配债权赎回异常，异常信息如下："+e.getMessage());
				if (e.getMessage() != null && e.getMessage().indexOf(CimsExceptionConstant.INTERACT_NETWORK_ERROR) > -1) {  
					retCode = CimsConstant.RET_CODE_TIMEOUT;   //超时
				} else {
					retCode = CimsConstant.RET_CODE_FAIL;
				}
				retMsg = "月还匹配债权赎回接口调用失败："+ e.getMessage()+"!";
				retMsg = retMsg.length() > 100 ? retMsg.substring(0, 100) : retMsg;
				redeemResultDto.setRetCode(retCode);
				redeemResultDto.setRetMsg(retMsg);
				redeemResultDto.setFrontTransNo(frontTransNo);
				transExceptionService.saveTransException(dto, redeemResultDto, retCode, cooperorgDealDTO.getDealCode());
			}
		}else{
			retMsg = "月还匹配债权赎回事务配置缺失!";
			retCode = CimsConstant.RET_CODE_FAIL;
		}
		resultMap.put("resultCode", retCode);
		resultMap.put("resultMsg", retMsg);
		return resultMap;
	}
	

	
	
	/**
	 * 得到贷款回购列表
	 * @param cooperorgDealDTO
	 * @return
	 * @throws Exception
	 */
	private BigDecimal getBuyBackMatchAmt(TCMmCooperorgDealDTO cooperorgDealDTO) throws Exception {
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("batchId", cooperorgDealDTO.getDealCode());
		BigDecimal matchAmt = buyBackDao.getBuyBackMatchAmt(paramMap);
		return matchAmt;
	}
	
	
	/**
	 * 贷款回购事务1:贷款转出批量回购处理
	 * 1. 主要将前端合作机构交易表的交易类型为贷款回购并且贷款明细流水表中符合条件信息封装成核心接口输入信息；
	 * 2. 调用核心接口后将贷款变更为我司贷款，将变更后的我司贷款进入我司债权池，调用会计API记会计账；
	 * 3. 变更【交易流水明细表】债权状态05-赎回；
	 * 4. 变更【债权明细表】债权状态05-赎回
	 * 其中合同编号=协议编号=债权编号
     * @throws Exception 
     * @Title doLoanTransferBatchRedeem
     * @return 
     * @author yanjingying
     * @date 2015-12-17-下午11:47:00
     * @update
     * @throws
	 * */
	private Map<String, Object> doBuyBackContract(TCMmCooperorgDealDTO cooperorgDealDTO, String frontTransNo) throws Exception{
		Map<String, Object> rsMap = new HashMap<String, Object>();
		//  获取交易流水明细表中回购贷款,并校验交易流水明细，若为空，则抛出异常，反之继续往下执行 
		List<TCMmCreditDealDetailDTO> creditDealDetailDTOList  = getBuyBackContractList(cooperorgDealDTO.getDealCode());
		if(creditDealDetailDTOList == null || creditDealDetailDTOList.size() == 0){
			throw new Exception("合作机构交易表的交易流水号："+cooperorgDealDTO.getDealCode()+":在【交易流水表明细表】中找不到相关明细信息！");
		}
		
		// 调用4037贷款回购确认接口
		RedeemResultDto redeemResultDto = callInterface4037(cooperorgDealDTO, frontTransNo,
				creditDealDetailDTOList);
		
		// 调用核心接口成功后，则更新债权状态05-赎回，赎回日期-当前确认日期
		if(redeemResultDto != null){
			if(CimsConstant.RET_CODE_SUC.equals(redeemResultDto.getRetCode())){
				String[] coreCreditStatus = new String[]{   
						CimsConstant.CORE_CREDIT_STATUS_LOANREDEEM, 
                        CimsConstant.CORE_CREDIT_STATUS_RED,
                        CimsConstant.CORE_CREDIT_STATUS_SETTLE_CANCEL};
				String[] creditStatus = new String[]{   
						CimsConstant.CREDIT_STATUS_WIN, 
                        CimsConstant.CREDIT_STATUS_END};
				//更新 贷款数据【交易流水明细表】债权状态05-赎回, 更新时间 ,赎回日期-当前确认日期
				dealService.updateTcmmCreditDealCreditorStatusByDealStreamCode(cooperorgDealDTO.getDealCode(), 
						CimsConstant.CREDIT_SOURCE_LOA, coreCreditStatus, creditStatus, CimsConstant.CREDIT_STATUS_RED);
				//更新【债权明细表】债权状态05-赎回, 赎回日期-当前确认日期
				dealService.updateTcmmCreditCreditorStatusByDealStreamCode(cooperorgDealDTO.getDealCode(), 
						CimsConstant.CREDIT_SOURCE_LOA, coreCreditStatus, creditStatus, CimsConstant.CREDIT_STATUS_RED);
			}
		} else {
			throw new Exception("合作机构交易表的交易流水号："+cooperorgDealDTO.getDealCode()+":调用核心接口(贷款转出批量回购)返回结果为空！");
		}
		rsMap.put("dto", redeemResultDto);
		return rsMap;
	}


	/**
	 * 调用4037贷款回购确认接口
	 * @param cooperorgDealDTO
	 * @param frontTransNo
	 * @param newCreditDetailDTOList
	 * @return
	 * @throws Exception
	 */
	private RedeemResultDto callInterface4037(TCMmCooperorgDealDTO cooperorgDealDTO, 
			String frontTransNo, List<TCMmCreditDealDetailDTO> creditDealDetailDTOList) throws Exception {
		// 封装贷款转出批量回购-回购参数DTO
		List<TCMmCreditDetailDTO> newCreditDetailDTOList = new ArrayList<TCMmCreditDetailDTO>();
		for(TCMmCreditDealDetailDTO dto : creditDealDetailDTOList){
			TCMmCreditDetailDTO creditDetailDTO = new TCMmCreditDetailDTO();
			creditDetailDTO.setTransferId(dto.getTransferId());       //债权转让编号
			creditDetailDTO.setCreditCode(dto.getCreditorId());       //债权编号
			creditDetailDTO.setRedeemDate(dto.getRedeemDate());       //赎回日期
			creditDetailDTO.setCooperorgCode(dto.getCooperorgCode()); //合作机构代码
			creditDetailDTO.setThisRepaySum(dto.getThisRepaySum());   //月还金额
			creditDetailDTO.setCoreCreditStatus(dto.getCoreCreditStatus());  //核心债权状态
			if (CimsConstant.CREDIT_STATUS_END.equals(dto.getCreditorStatus())
					&& CimsConstant.CORE_CREDIT_STATUS_TRANSFER.equals(dto.getCoreCreditStatus())) {
				//债权状态泯灭、核心状态为正常，表示同步核心失败，需修改核心状态为提前结清
				creditDetailDTO.setCoreCreditStatus(CimsConstant.CORE_CREDIT_STATUS_SETTLE_AHEAD);  //核心债权状态
			}
			creditDetailDTO.setProductType(dto.getProductType());//产品类型
			newCreditDetailDTOList.add(creditDetailDTO);              //贷款明细对象
		}
		
		RedeemParamDto redeemParamDto = new RedeemParamDto();
		redeemParamDto.setDealCode(cooperorgDealDTO.getDealCode());  //交易流水号
		redeemParamDto.setCCode(cooperorgDealDTO.getCooperorgCode());  //合作机构代码
		redeemParamDto.settCMmCreditDetailDTOList(newCreditDetailDTOList);  //债权明细，此处债权方式处理
		redeemParamDto.setFrontTransNo(frontTransNo);//前置流水号
		//  调用核心接口-贷款转出批量回购（说明：测试过程中测试接口时再调用）
		RedeemResultDto redeemResultDto = iCInteract.sendLoanTransferBatchRedeemToCore(redeemParamDto);
		return redeemResultDto;
	}
	
	

	
	/**
	 * 贷款回购事务2:贷款转出月还匹配债权赎回处理
	 * 1. 主要将贷款转出时月还匹配出剩余期数债权赎回，封装成核心接口输入信息；
	 * 2. 调用核心接口-转让债权批量赎回，将赎回该批次债权，调用会计API记会计账；
	 * 3. 单个事务调用成功后则更新债权明细表债权状态05-赎回、本期还款金额0、当前债权价值0；
     * @throws Exception 
     * @Title doLoanTransferRePayMatchCreditRedeem
     * @return 
     * @author yanjingying
     * @date 2015-12-17-下午11:47:00
     * @update
     * @throws
	 * */
	private Map<String, Object> doBuyBackCredit(TCMmCooperorgDealDTO cooperorgDealDTO, String frontTransNo)  throws Exception{
		RedeemResultDto redeemResultDto = null;
		Map<String, Object> rsMap = new HashMap<String, Object>();
		//回购匹债权金额
		BigDecimal matchAmtTotal = getBuyBackMatchAmt(cooperorgDealDTO);
		if (matchAmtTotal == null || matchAmtTotal.compareTo(BigDecimal.ONE) < 0) {
			rsMap.put("isInvoke", "false");
		}else{
			rsMap.put("isInvoke", "true");
			
			//判断该包下除了回购批次的债权，是否存在已确认/泯灭状态的债权
			int creditCnt = getCreditNumInPack(cooperorgDealDTO);
			//查询二次购买包后缀
			String suffix = getSuffix(cooperorgDealDTO);
			//得到二次购买包下债权明细
			List<TCMmCreditDetailDTO> matchList = getSecondPackCredit(cooperorgDealDTO, suffix);
			//赎回确认日期
			Date redeemDate = new Date();
			//赎回债权列表（总）
			List<CreditDetailDto> backAllList = new ArrayList<CreditDetailDto>();
			//赎回债权列表（全部赎回的情况）
			List<String> backWholeList = new ArrayList<String>();
			//赎回债权列表（部分赎回的情况）
			List<String> backPartList = new ArrayList<String>();
			//匹债权赎回批次号
			String dealCodeCredit = iCDeal.createDealCode(CimsConstant.BIZNO_TYPE_REDEMPTION);
			String dealCodeContract = cooperorgDealDTO.getDealCode();
			List<TCMmDealMatchDTO> saveMatchList = new ArrayList<TCMmDealMatchDTO>();
			if (creditCnt > 0) {
				//二次购买包按金额赎回 
				for (TCMmCreditDetailDTO matchDto : matchList) {
					//如果小于1块钱，不再匹配
					if (matchAmtTotal.compareTo(BigDecimal.ONE) < 0) {
						break;
					}
					String transferId = matchDto.getTransferId();
					//赎回日为当天，所以赎回价值为当前价值
					BigDecimal matchAmt = matchDto.getThisCreditorValue();
					matchAmtTotal = matchAmtTotal.subtract(matchAmt);
					if (matchAmtTotal.compareTo(BigDecimal.ZERO) > 0) {
						//剩余金额大于0，继续匹配要赎回债权
						backAllList.add(getCreditDetailDto(matchDto, redeemDate, "Y", null));
						backWholeList.add(transferId);
						setMatchCredit(saveMatchList, dealCodeCredit, dealCodeContract, matchDto, redeemDate, "Y", null);//设置贷款回购匹债权信息list
					} else if (matchAmtTotal.compareTo(BigDecimal.ZERO) < 0) {
						//剩余金额小于0
						if (matchAmtTotal.compareTo(new BigDecimal(-1)) > 0) {
							//如果剩余金额小于0且大于-1，则匹全部债权，并且结束 // 9.5-10=-0.5 
							backAllList.add(getCreditDetailDto(matchDto, redeemDate, "Y", null));
							backWholeList.add(transferId);
							setMatchCredit(saveMatchList, dealCodeCredit, dealCodeContract, matchDto, redeemDate, "Y", null);//设置贷款回购匹债权信息list
							break;
						}
						//匹配部分赎回债权 // 3-10=-7 
						BigDecimal backValue = matchAmtTotal.add(matchAmt);
						backAllList.add(getCreditDetailDto(matchDto, redeemDate, "N", backValue));//部分赎回
						backPartList.add(transferId);
						setMatchCredit(saveMatchList, dealCodeCredit, dealCodeContract, matchDto, redeemDate, "N", backValue);//设置贷款回购匹债权信息list
						break;
					} else {
						//金额刚好匹配到最后一条债权
						break;
					}
				}
			} else {
				//二次购买包全部赎回
				for (TCMmCreditDetailDTO matchDto : matchList) {
					String transferId = matchDto.getTransferId();
					backAllList.add(getCreditDetailDto(matchDto, redeemDate, "Y", null));
					backWholeList.add(transferId);
					setMatchCredit(saveMatchList, dealCodeCredit, dealCodeContract, matchDto, redeemDate, "Y", null);//设置贷款回购匹债权信息list
				}
			}

			if(backAllList != null && backAllList.size() > 0){
				//4 调用核心接口-转让债权批量赎回（说明：测试过程中测试接口时再调用）
				redeemResultDto = callInterface4023(cooperorgDealDTO,
						frontTransNo, backAllList, dealCodeCredit);
				//5 调用核心接口成功后，则更新债权状态05-赎回，赎回日期-当前确认日期
				updateCredit(backWholeList, backPartList, redeemDate, redeemResultDto, saveMatchList);
				
			} 
		}
		rsMap.put("dto", redeemResultDto);
		return rsMap;
	}


	/**
	 * 调用4023债权赎回接口
	 * @param cooperorgDealDTO
	 * @param frontTransNo
	 * @param backAllList
	 * @param dealCodeCredit
	 * @return
	 * @throws Exception
	 */
	private RedeemResultDto callInterface4023(
			TCMmCooperorgDealDTO cooperorgDealDTO, String frontTransNo,
			List<CreditDetailDto> backAllList, String dealCodeCredit)
			throws Exception {
		RedeemResultDto redeemResultDto = null;
		RedeemParamDto redeemParamDto = new RedeemParamDto();    
		redeemParamDto.setDealCode(dealCodeCredit);   //交易流水号
		redeemParamDto.setCreditDetailList(backAllList);         //债权明细对象
		redeemParamDto.setFrontTransNo(frontTransNo);//前置流水号
		redeemParamDto.setCCode(cooperorgDealDTO.getCooperorgCode());//合作机构
		redeemParamDto.setBizType("3");
		redeemResultDto = iCInteract.redeemCreditRight(redeemParamDto);
		if(redeemResultDto == null){
			throw new Exception("合作机构交易表的交易流水号："+cooperorgDealDTO.getDealCode()+":调用核心接口(贷款转出月还匹配债权赎回)返回结果为空！");
		}
		return redeemResultDto;
	}


	/**
	 * 得到二次购买包下债权明细
	 * @param cooperorgDealDTO
	 * @param suffix
	 * @return
	 */
	private List<TCMmCreditDetailDTO> getSecondPackCredit(
			TCMmCooperorgDealDTO cooperorgDealDTO, String suffix) {
		String secondPackName = cooperorgDealDTO.getCreditPackageName() + suffix;
		Map<String, Object> searchParams = new HashMap<String, Object>();
		TCMmCreditDetailDTO dto = new TCMmCreditDetailDTO();
		dto.setPackageNum(secondPackName);
		dto.setCreditSource(CimsConstant.CREDIT_SOURCE_CRE);//来源:01-债权
		dto.setValidateState("1");
		searchParams.put("dto", dto);
		searchParams.put("creditStatuss", new String[] {CimsConstant.CREDIT_STATUS_WIN});
		//二次购买包下债权明细
		List<TCMmCreditDetailDTO> matchList = buyBackDao.searchCreditDetail(searchParams);
		if (CollectionsUtils.isEmpty(matchList)) {
			throw new RuntimeException("二次购买包下没有已确认的债权，包名:" + secondPackName+ ", 回购批次号:" + cooperorgDealDTO.getDealCode());
		}
		return matchList;
	}


	/**
	 * 得到二次购买包后缀
	 * @param cooperorgDealDTO
	 * @return
	 */
	private String getSuffix(TCMmCooperorgDealDTO cooperorgDealDTO) {
		Map<String, Object> paramMap1 = new HashMap<String, Object>();
		paramMap1.put("dealCode", cooperorgDealDTO.getDealCode());
		String suffix = buyBackDao.getSecondPackSuffix(paramMap1);
		if (StringUtils.isEmpty(suffix)) {
			throw new RuntimeException("二次购买包后缀没有找到，批次号:" + cooperorgDealDTO.getDealCode() + ",所属合约编号:"+cooperorgDealDTO.getContractCode());
		}
		return suffix;
	}


	/**
	 * 在回购包下是否有批次以外的债权
	 * @param cooperorgDealDTO
	 * @return
	 */
	private int getCreditNumInPack(TCMmCooperorgDealDTO cooperorgDealDTO) {
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("packageNum", cooperorgDealDTO.getCreditPackageName());
		paramMap.put("contractCode", cooperorgDealDTO.getContractCode());
		paramMap.put("cCode", cooperorgDealDTO.getCooperorgCode());
		paramMap.put("creditorStatuss", new String[] {CimsConstant.CREDIT_STATUS_WIN, CimsConstant.CREDIT_STATUS_END});
		paramMap.put("coreStatuss", new String[] {CimsConstant.CORE_CREDIT_STATUS_LOANREDEEM, 
												CimsConstant.CORE_CREDIT_STATUS_RED, 
												CimsConstant.CORE_CREDIT_STATUS_SETTLE_CANCEL});
		paramMap.put("dealCode", cooperorgDealDTO.getDealCode());
		int creditCnt = buyBackDao.getPackCreditNum(paramMap);
		return creditCnt;
	}
	
	/**
	 * 更新债权
	 * @param backWholeList
	 * @param backPartList
	 * @param redeemDate
	 * @param redeemResultDto
	 * @throws Exception 
	 */
	private void updateCredit(List<String> backWholeList, List<String> backPartList, Date redeemDate, 
			RedeemResultDto redeemResultDto, List<TCMmDealMatchDTO> saveMatchList) throws Exception {
		if (CimsConstant.RET_CODE_SUC.equals(redeemResultDto.getRetCode())) {
			//更新债权明细（全部赎回）每次不能大于1000条
			List<List<String>> splitList =  CollectionsUtils.splitList(backWholeList, CollectionsUtils.LIST_SIZE);
			if (CollectionsUtils.isNotEmpty(splitList)) {
				for (List<String> perList : splitList) {
					if (CollectionsUtils.isNotEmpty(perList)) {
						updateCreditWholeRedeem(perList, redeemDate);
					}
				}
			}
		
			//更新债权明细（部分赎回）
			if (CollectionsUtils.isNotEmpty(backPartList)) {
				String partRedeemTransferId = backPartList.get(0);
				List<ResponseBackCreditValueDTO> rsList = redeemResultDto.getCreditList();
				for (ResponseBackCreditValueDTO resp : rsList) {
					if (partRedeemTransferId.equals(resp.getTransferId())) {
						BigDecimal redeemRepay = resp.getDeliveryEachRepaymentValue();
						BigDecimal redeemValue = resp.getDeliveryCreditValue();
						updateCreditPartRedeem(partRedeemTransferId, redeemRepay, redeemValue);
						break;
					}
				}
			}
			//保存匹债权明细表
			if (CollectionsUtils.isNotEmpty(saveMatchList)) {
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("list", saveMatchList);
				dealMatchDao.insertTCMmDealMatchBatch(map);
			}
		}
		
	}
	
	
	/**
	 * 更新债权明细（全部赎回）
	 * @param backWholeList
	 * @param redeemDate
	 */
	private void updateCreditWholeRedeem(List<String> backWholeList, Date redeemDate) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("creditorStatus", CimsConstant.CREDIT_STATUS_RED);
		map.put("redeemDate", redeemDate);
		map.put("backList", backWholeList);
		buyBackDao.updateWholeBackCredit(map);
	}
	
	/**
	 * 更新债权明细（部分赎回）
	 * @param partRedeemTransferId
	 * @param thisRepaySumRedeem
	 * @param thisCreditorValueRedeem
	 * @throws Exception
	 */
	private void updateCreditPartRedeem(String partRedeemTransferId, BigDecimal redeemRepay, BigDecimal redeemValue) throws Exception {
		Map<String, Object> param = new HashMap<String, Object>();
		TCMmCreditDetailDTO dto = new TCMmCreditDetailDTO();
		dto.setTransferId(partRedeemTransferId);
		param.put("dto", dto);
		List<TCMmCreditDetailDTO> creditDetailList = creditDetailService.searchTCMmCreditDetail(param);
		if (CollectionsUtils.isNotEmpty(creditDetailList)) {
			TCMmCreditDetailDTO creditDetail = creditDetailList.get(0);
			//更新当前价值
			BigDecimal thisCreditorValueCurr = creditDetail.getThisCreditorValue();
			thisCreditorValueCurr = thisCreditorValueCurr.subtract(redeemValue);
			if (thisCreditorValueCurr.compareTo(BigDecimal.ZERO) < 0) {
				thisCreditorValueCurr = BigDecimal.ZERO;
			}
			//更新月还
			BigDecimal thisRepaySumCurr = creditDetail.getThisRepaySum();
			thisRepaySumCurr = thisRepaySumCurr.subtract(redeemRepay);
			if (thisRepaySumCurr.compareTo(BigDecimal.ZERO) < 0) {
				thisRepaySumCurr = BigDecimal.ZERO;
			}
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("thisCreditorValue", thisCreditorValueCurr);
			map.put("thisRepaySum", thisRepaySumCurr);
			map.put("transferId", partRedeemTransferId);
			buyBackDao.updatePartBackCredit(map);
		}
	
	}
	
	/**
	 * 组织调用接口参数
	 * @param credit
	 * @param redeemDate
	 * @param isWhole
	 * @param backValue
	 * @return
	 */
	private CreditDetailDto getCreditDetailDto(TCMmCreditDetailDTO credit, Date redeemDate, String isWhole, BigDecimal backValue) {
		CreditDetailDto creditDetailDto = new CreditDetailDto();
		creditDetailDto.setTransferId(credit.getTransferId());   //债权转让编号
		creditDetailDto.setCreditCode(credit.getCreditCode());   //债权编号
		creditDetailDto.setIsWhole(isWhole);                           //是否全部赎回
		creditDetailDto.setThisCreditorValue(backValue == null ? credit.getThisCreditorValue() : backValue); //本次赎回债权价值
		creditDetailDto.setRedeemDate(redeemDate);   				//赎回日期
		return creditDetailDto;
	}

	/**
	 * 保存匹配债权表
	 * @param credit
	 * @param redeemDate
	 * @param isWhole
	 * @param backValue
	 * @return
	 */
	private void setMatchCredit(List<TCMmDealMatchDTO> saveMatchList, String dealCodeCredit, 
			String dealCodeContract, TCMmCreditDetailDTO credit, Date redeemDate, String isWhole, BigDecimal backValue) {
		TCMmDealMatchDTO dto = new TCMmDealMatchDTO();
		dto.setDealCode(dealCodeCredit);
		dto.setBackLoanDealCode(dealCodeContract);
		dto.setTransferId(credit.getTransferId());
		dto.setBackValue(backValue == null ? credit.getThisCreditorValue() : backValue);
		dto.setIsWhole(isWhole);
		dto.setBackDate(redeemDate);
		saveMatchList.add(dto);
	}
	
	
}